package org.xx.armory.spring5.autoconfigure;

import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.BeanNameViewResolver;
import org.xx.armory.spring5.mvc.ActiveBreakerController;
import org.xx.armory.spring5.mvc.AddAuthenticationToViewInterceptor;
import org.xx.armory.spring5.mvc.ArmoryErrorAttributes;
import org.xx.armory.spring5.mvc.ArmoryMappingJackson2JsonView;
import org.xx.armory.spring5.mvc.GlobalErrorHandler;
import org.xx.armory.spring5.mvc.LogInterceptor;
import org.xx.armory.spring5.mvc.OutputCacheInterceptor;
import org.xx.armory.spring5.mvc.RewriteSimpleURLInterceptor;
import org.xx.armory.spring5.mvc.SelfTestController;
import org.xx.armory.spring5.mvc.VerifyRequestParamsSignatureInterceptor;

import static org.xx.armory.spring5.mvc.ModelUtils.JSON_VIEW;

@Configuration
@ConditionalOnWebApplication
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@AutoConfigureBefore({WebMvcAutoConfiguration.class, ErrorMvcAutoConfiguration.class})
public class ArmoryWebMvcAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnExpression("${armory.diagnosis:true}")
    public ActiveBreakerController activeBreakerController() {
        return new ActiveBreakerController();
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnExpression("${armory.diagnosis:true}")
    public SelfTestController selfTestController() {
        return new SelfTestController();
    }

    @Bean
    @ConditionalOnMissingBean
    public GlobalErrorHandler globalErrorHandler() {
        return new GlobalErrorHandler();
    }

    @Bean
    @ConditionalOnMissingBean
    public ErrorAttributes errorAttributesBean() {
        return new ArmoryErrorAttributes();
    }

    @Bean(name = JSON_VIEW)
    @ConditionalOnMissingBean(name = JSON_VIEW)
    public View jsonTemplateBean() {
        final var result = new ArmoryMappingJackson2JsonView();

        // 允许输出Content-Length头。
        result.setUpdateContentLength(true);

        return result;
    }

    @Bean
    @ConditionalOnMissingBean
    public BeanNameViewResolver beanNameResolverBean() {
        return new BeanNameViewResolver();
    }

    @Bean
    @ConditionalOnMissingBean
    public LogInterceptor logInterceptorBean() {
        return new LogInterceptor();
    }

    @Bean
    @ConditionalOnMissingBean
    public VerifyRequestParamsSignatureInterceptor verifyRequestSignatureInterceptorBean() {
        return new VerifyRequestParamsSignatureInterceptor();
    }

    @Bean
    @ConditionalOnMissingBean
    public OutputCacheInterceptor outputCacheInterceptorBean() {
        return new OutputCacheInterceptor();
    }

    @Bean
    @ConditionalOnMissingBean
    public RewriteSimpleURLInterceptor rewriteSimpleURLInterceptor() {
        return new RewriteSimpleURLInterceptor();
    }

    @Bean
    @ConditionalOnMissingBean
    public AddAuthenticationToViewInterceptor addAuthenticationToViewInterceptorBean() {
        return new AddAuthenticationToViewInterceptor();
    }
}
